<?php
class DiagnosticController extends CController
{
    protected $checkList = array(
        array('title' => 'Check assets folder', 'checker' => 'checkAssetsFolder'),
        array('title' => 'Check runtime folder', 'checker' => 'checkRuntimeFolder'),
        array('title' => 'Check database connections', 'checker' => 'checkDBConnections'),
        
        // specific for CMS
        array('title' => 'Sites managed by the CMS', 'checker' => 'listSites'),
        array('title' => 'Site themes must be writable', 'checker' => 'checkSiteThemes'),
    );
    
    
    public function actionIndex(){
        // the exception.php view need to be cleaned up for console app, remove most of the HTML tags
        Yii::app()->setSystemViewPath(Yii::getPathOfAlias('application.views.console-system'));
        
        
        echo "\n";
        echo "Checking the running environment for ".Yii::app()->name."\n";
        echo "\n";
        
        foreach($this->checkList as $check) {
            echo str_pad('',strlen($check['title']),'=')."\n";
            echo $check['title']."\n";
            echo str_pad('',strlen($check['title']),'=')."\n";

            $check['errors'] = array();

            call_user_func_array(array($this, $check['checker']), array(&$check));
            if ($check['errors']) {
                foreach($check['errors'] as $err)
                    echo "  {$err}\n";
            } else
                echo "  OK\n";
            
            echo "\n";
        }
        
        echo "Finished !!!\n";
    }
    
    public function checkAssetsFolder(& $check){
        $path = Yii::getPathOfAlias('webroot.assets');
        echo $path."\n";
        if (!file_exists($path))
            $check['errors'][] = "'assets' folder not found.";
        elseif(!is_writable($path)) {
            try{
                $this->chmodr($path,0777);
            } catch(Exception $ex) {
                $check['errors'][] = "'assets' folder is not writable.";
            }
        }
    }

    public function checkRuntimeFolder(& $check){
        // runtime
        $path = Yii::getPathOfAlias('application.runtime');
        echo $path."\n";
        if (!file_exists($path))
            $check['errors'][] = "'runtime' folder not found.";
        else {
            // cache
            echo $path.'/cache'."\n";
            if (!file_exists($path.'/cache'))
                $check['errors'][] = "'runtime/cache' folder not found.";
        }
        
        // check if writable
        if(!is_writable($path)) {
            try{
                $this->chmodr($path,0777);
            } catch(Exception $ex) {
                $check['errors'][] = "'runtime' folder is not writable.";
            }
        }
    }
    
    public function checkDBConnections(& $check) {
        if ($_SERVER['argc'] < 2){
            $check['errors'][] = "You need to specify the domain to check for database connection.\n  php index-console.php <domain.name>\n";
            return;
        }
        
        $site = $_SERVER['argv'][1];
        
        // include environment.php
        $envFile = Yii::app()->basePath.'/config/environment.php';
        if (!file_exists($envFile)) {
            $check['errors'][] = "environment.php file is not found.";
            return;
        }
        
        require $envFile;

        // test default database
        if (!isset($dbs['default']) || !is_array($dbs['default']))
            $check['errors'][] = "Warning: No default database connection.\n";
            
        // test all db connections
        foreach($dbs as $key => $db) {
            echo "Testing {$key} connection\n";
            $con = new CDbConnection($db['connectionString'],$db['username'],$db['password']);
            try {
            $con->Active = true;
            } catch (CDbException $e) {
                $check['errors'][] = $e->getMessage()."\n".print_r($db, true)."\n";
            }
        }
        
    }
    
    public function listSites() {
        Yii::import('Cms.models.Site');
        $sites = Site::model()->findAll();
        foreach($sites as $site)
            echo "{$site->id}\t=> {$site->name}\n";
    }
    
    
    public function checkSiteThemes($check) {
        Yii::import('Cms.models.Site');
        $sites = Site::model()->findAll();
        foreach($sites as $site) {
            echo "Checking theme folder of {$site->name}...";
            Yii::app()->theme = $site->name;
            if (Yii::app()->theme instanceof CTheme) {
                $folder = Yii::app()->theme->getBasePath();
                echo "OK. Try to make it writable...";
                try {
                    $this->chmodr($folder, 0777);
                    echo "OK\n";
                }catch(Exception $e) {
                    echo $e->getMessage()."\n";
                }
            } else {
                echo "\n\tTheme folder {$site->name} is not found.\n";
            }
        }
    }
    
    /**
    * chmod recursive
    * 
    * @param mixed $path
    * @param mixed $filemode
    * @return bool
    */
    protected function chmodr($path, $filemode) {
        if (!is_dir($path))
            return @chmod($path, $filemode);
        
        $dh = opendir($path);
        while (($file = readdir($dh)) !== false) {
            if($file != '.' && $file != '..') {
                $fullpath = $path.'/'.$file;
                if(is_link($fullpath))
                    return FALSE;
                elseif(!is_dir($fullpath) && !@chmod($fullpath, $filemode))
                        return FALSE;
                elseif(!$this->chmodr($fullpath, $filemode))
                    return FALSE;
            }
        }

        closedir($dh);

        if(@chmod($path, $filemode))
            return TRUE;
        else
            return FALSE;
    }
}
?>
